package com.cycplus.test.extensions

import androidx.appcompat.app.AppCompatActivity
import androidx.fragment.app.Fragment
import androidx.lifecycle.ViewModel
import androidx.lifecycle.ViewModelProvider
import androidx.lifecycle.ViewModelStoreOwner
import io.reactivex.Observable
import io.reactivex.disposables.Disposable
import io.reactivex.schedulers.Schedulers
import java.io.ByteArrayOutputStream
import java.util.regex.Matcher
import java.util.regex.Pattern
import java.util.zip.Deflater
import java.util.zip.DeflaterOutputStream

inline fun <reified T : ViewModel> Fragment.obtainFragmentScopeViewModel(modelClass: Class<T>): T {
    return ViewModelProvider(this, ViewModelProvider.NewInstanceFactory())[modelClass]
}

inline fun <reified T : ViewModel> Fragment.obtainActivityScopeViewModel(modelClass: Class<T>): T {
    return ViewModelProvider(requireActivity(), ViewModelProvider.NewInstanceFactory())[modelClass]
}

inline fun <reified T : ViewModel> Fragment.obtainApplicationScopeViewModel(modelClass: Class<T>): T {
    return ViewModelProvider(requireActivity().application as ViewModelStoreOwner , ViewModelProvider.NewInstanceFactory())[modelClass]
}

fun <T : ViewModel> Fragment.safelyObtainApplicationScopeViewModel(modelClass: Class<T>): T? {
    return activity?.application?.let {
        if (it !is ViewModelStoreOwner) {
            throw RuntimeException("your Application must extends ViewModelStoreOwner to use ApplicationViewModelStore when invoke this method")
        }
        val factory = ViewModelProvider.NewInstanceFactory()
        return ViewModelProvider(it, factory)[modelClass]
    }
}

inline fun <reified T : ViewModel> AppCompatActivity.obtainActivityScopeViewModel(modelClass: Class<T>): T {
    return ViewModelProvider(this, ViewModelProvider.NewInstanceFactory())[modelClass]
}

inline fun <reified T : ViewModel> AppCompatActivity.obtainApplicationScopeViewModel(modelClass: Class<T>): T {
    return ViewModelProvider(this.application as ViewModelStoreOwner , ViewModelProvider.NewInstanceFactory())[modelClass]
}

fun <T : ViewModel> AppCompatActivity.safelyObtainApplicationScopeViewModel(modelClass: Class<T>): T? {
    return application?.let {
        if (it !is ViewModelStoreOwner) {
            throw RuntimeException("your Application must extends ViewModelStoreOwner to use ApplicationViewModelStore when invoke this method")
        }
        val factory = ViewModelProvider.NewInstanceFactory()
        return ViewModelProvider(it, factory)[modelClass]
    }
}

fun String.lastCharIsLetter(): Boolean {
    val lastChar = this.lastOrNull() ?: return false
    return lastChar in 'a'..'z' || lastChar in 'A'..'Z'
}

fun String.insertAt(index: Int, str: String): String {
    return take(index) + str + drop(index)
}

fun String.isAllDigits(): Boolean {
    return all { it.isDigit() }
}

fun String.desensitizePhoneNumber():String{
    return if(isAllDigits() && length > 7){
        val start = this.substring(0, 3)
        val end = this.substring(this.length - 4)
        "$start****$end"
    }else {
        this
    }
}

//是否包含数字
fun String.containsDigits(): Boolean {
    return any { it.isDigit() }
}

//是否包含字母
fun String.containsLetters(): Boolean {
    return any { it.isLetter() }
}

fun String.containsSpecialCharacter(): Boolean {
    val pattern: Pattern = Pattern.compile("[^a-zA-Z0-9]")
    val matcher: Matcher = pattern.matcher(this)
    return matcher.find()
}

fun ByteArray.gzipCompressed(): ByteArray? {
    if (this.isEmpty()) {
        return null
    }

    return try {
        val outputStream = ByteArrayOutputStream()
        DeflaterOutputStream(outputStream, Deflater(Deflater.DEFAULT_COMPRESSION, true)).use { dos ->
            dos.write(this)
            dos.finish()
        }
        outputStream.toByteArray()
    } catch (e: Exception) {
        e.printStackTrace()
        null
    }
}

fun asyncTask(task: () -> Unit): Disposable? {
    return Observable.just("")
        .map {
            task.invoke()
            it
        }
        .subscribeOn(Schedulers.io())
        .subscribe {}
}